﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutomatasPrj
{
    class Program
    {
        static void Main(string[] args)
        {
            //TestClausuraEpsilon();
            //TestAFND();
            TestAFNDEpsilon();

            // Wait
            Console.Read();
        }

        static void TestAFNDEpsilon()
        {
            // AFND que acepte todos los string tal que
            // uno de los ultimos 4 es un uno.

            Estado q0 = new Estado("q0");
            Estado q1 = new Estado("q1");
            Estado q2 = new Estado("q2");
            Estado q3 = new Estado("q3");
            Estado q4 = new Estado("q4");

            DeltaAFND delta = new DeltaAFND();

            delta.AddValue(q0, '0', q0);
            delta.AddValue(q0, '1', q0);
            delta.AddValue(q0, '1', q1);

            delta.AddValue(q1, '0', q2);
            delta.AddValue(q1, '1', q2);
            delta.AddValue(q1, '\0', q2);

            delta.AddValue(q2, '0', q3);
            delta.AddValue(q2, '1', q3);
            delta.AddValue(q2, '\0', q3);

            delta.AddValue(q3, '0', q4);
            delta.AddValue(q3, '1', q4);
            delta.AddValue(q3, '\0', q4);

            AFNDEpsilon afndEpsilon = new AFNDEpsilon(q0, new Estado[] { q0, q1, q2, q3, q4 }, delta, new Estado[] { q4 });

            Console.WriteLine(afndEpsilon.Accepts("010100"));
        }

        static void TestClausuraEpsilon()
        {
            Estado q0 = new Estado("q0");
            Estado q1 = new Estado("q1");
            Estado q2 = new Estado("q2");
            Estado q3 = new Estado("q3");
            Estado q4 = new Estado("q4");
            Estado q5 = new Estado("q5");
            Estado q6 = new Estado("q6");

            DeltaAFND delta = new DeltaAFND();

            delta.AddValue(q0, '\0', q1);
            delta.AddValue(q0, '\0', q3);
            delta.AddValue(q1, '\0', q2);
            delta.AddValue(q2, '\0', q5);
            delta.AddValue(q3, 'a', q4);
            delta.AddValue(q4, 'b', q5);
            delta.AddValue(q4, '\0', q6);

            PrintSet(delta.ClausuraEpsilon(new HashSet<Estado> { q0, q3 }));
        }

        static void TestAFD()
        {
            Estado a = new Estado("a");
            Estado b = new Estado("b");
            Estado c = new Estado("c");
            Estado d = new Estado("d");
            Estado e = new Estado("e");
            Estado f = new Estado("f");
            Estado g = new Estado("g");
            Estado h = new Estado("h");

            DeltaAFD delta = new DeltaAFD();

            delta.AddValue(a, '0', b);
            delta.AddValue(a, '1', f);

            delta.AddValue(b, '0', g);
            delta.AddValue(b, '1', c);

            delta.AddValue(c, '0', a);
            delta.AddValue(c, '1', c);

            delta.AddValue(d, '0', c);
            delta.AddValue(d, '1', g);

            delta.AddValue(e, '0', h);
            delta.AddValue(e, '1', f);

            delta.AddValue(f, '0', c);
            delta.AddValue(f, '1', g);

            delta.AddValue(g, '0', f);
            delta.AddValue(g, '1', f);

            delta.AddValue(h, '0', g);
            delta.AddValue(h, '1', c);

            AFD afd = new AFD(a, delta, new Estado[] { c });

            Console.WriteLine(afd.Accepts("01001"));
        }

        static void TestAFND()
        {
            Estado a = new Estado("a");
            Estado b = new Estado("b");
            Estado c = new Estado("c");

            DeltaAFND delta = new DeltaAFND();

            delta.AddValue(a, '0', a);
            delta.AddValue(a, '0', b);
            delta.AddValue(a, '1', a);
            delta.AddValue(b, '1', c);

            AFND afnd = new AFND(a, 
                                new Estado[] { a, b, c }, 
                                delta, 
                                new Estado[] { c });

            Console.WriteLine(afnd.Accepts("00000001"));
        }

        static void PrintSet(HashSet<Estado> lista)
        {
            foreach (Estado q in lista)
                Console.WriteLine("lista: " + q);
        }
    }
}
